From 78acc7398912856fe3c7b5a3a681ca25718df564 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 10 Sep 2014 07:47:11 -0700 Subject: [PATCH] Don't blow away checked out git repos This primarily blows away all *submodules* as well, which sometimes can be quite large and take some time to update. Instead, re-use an existing checkout, just reset it to the right revision if possible. Also, move the submodule update step to occur unconditionally to account for corrupt submodule checkouts or interrupted downloads. This update step should be much faster than `git submodule update` because we're using libgit2, so yay! --- src/cargo/sources/git/utils.rs | 48 +++++++++++++++++----------- tests/test_cargo_compile_git_deps.rs | 3 +- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/cargo/sources/git/utils.rs b/src/cargo/sources/git/utils.rs index 31f65bc3e..dfdb7e9ac 100644 --- a/src/cargo/sources/git/utils.rs +++ b/src/cargo/sources/git/utils.rs @@ -202,20 +202,22 @@ impl GitDatabase { pub fn copy_to(&self, rev: GitRevision, dest: &Path) -> CargoResult { - match git2::Repository::open(dest) { + let checkout = match git2::Repository::open(dest) { Ok(repo) => { - let is_fresh = match repo.revparse_single("HEAD") { - Ok(head) => head.id().to_string() == rev.to_string(), - _ => false, - }; - if is_fresh { - return Ok(GitCheckout::new(dest, self, rev, repo)) + let checkout = GitCheckout::new(dest, self, rev, repo); + if !checkout.is_fresh() { + try!(checkout.fetch()); + try!(checkout.reset()); + assert!(checkout.is_fresh()); } + checkout } - _ => {} - } - - GitCheckout::clone_into(dest, self, rev) + Err(..) => try!(GitCheckout::clone_into(dest, self, rev)), + }; + try!(checkout.update_submodules().chain_error(|| { + internal("failed to update submodules") + })); + Ok(checkout) } pub fn rev_for(&self, reference: S) -> CargoResult { @@ -248,14 +250,7 @@ impl<'a> GitCheckout<'a> { { let repo = try!(GitCheckout::clone_repo(database.get_path(), into)); let checkout = GitCheckout::new(into, database, revision, repo); - - try!(checkout.reset().chain_error(|| { - internal("failed to reset to the right revision") - })); - try!(checkout.update_submodules().chain_error(|| { - internal("failed to update submodules") - })); - + try!(checkout.reset()); Ok(checkout) } @@ -286,6 +281,21 @@ impl<'a> GitCheckout<'a> { Ok(repo) } + fn is_fresh(&self) -> bool { + match self.repo.revparse_single("HEAD") { + Ok(head) => head.id().to_string() == self.revision.to_string(), + _ => false, + } + } + + fn fetch(&self) -> CargoResult<()> { + info!("fetch {}", self.repo.path().display()); + let url = try!(self.database.path.to_url().map_err(human)); + let url = url.to_string(); + try!(fetch(&self.repo, url.as_slice())); + Ok(()) + } + fn reset(&self) -> CargoResult<()> { info!("reset {} to {}", self.repo.path().display(), self.revision.as_slice()); diff --git a/tests/test_cargo_compile_git_deps.rs b/tests/test_cargo_compile_git_deps.rs index 90e66ca7a..de4c05ec1 100644 --- a/tests/test_cargo_compile_git_deps.rs +++ b/tests/test_cargo_compile_git_deps.rs @@ -475,8 +475,7 @@ test!(two_revs_same_deps { baz.build(); - // TODO: -j1 is a hack - assert_that(foo.cargo_process("build").arg("-j").arg("1"), + assert_that(foo.cargo_process("build"), execs().with_status(0)); assert_that(&foo.bin("foo"), existing_file()); assert_that(foo.process(foo.bin("foo")), execs().with_status(0)); -- 2.30.2